<template>
  <div class="blog-toc-container">
    <RightList :list="tocWithSelect" title="目录" @select="handleSelect" class="rightList" />
  </div>
</template>

<script setup lang="ts">
import RightList from './RightList.vue'
import { debounce } from '@/utils'
import { ref, computed, onUnmounted, getCurrentInstance, type ComponentPublicInstance } from 'vue'
type propsType = {
  toc: any[]
}
const $emit = defineEmits(['select'])
const props = defineProps<propsType>()
const activeAnchor = ref('')
const tocWithSelect = computed(() => {
  const getTOC = (toc: any[] = []): any[] => {
    return toc.map((t: any) => ({
      ...t,
      isSelect: t.anchor === activeAnchor.value,
      children: getTOC(t.children)
    }))
  }
  return getTOC(props.toc)
})
const doms = computed(() => {
  const doms: any[] = []
  const addToDoms = (toc: any[]) => {
    for (const t of toc) {
      doms.push(document.getElementById(t.anchor))
      if (t.children && t.children.length) {
        addToDoms(t.children)
      }
    }
  }
  addToDoms(props.toc)
  return doms
})
const proxy: ComponentPublicInstance<any> = getCurrentInstance()?.proxy
const setSelectDebounce = debounce(setSelect, 50)
proxy.$mybus.on('mainScroll', setSelectDebounce)
onUnmounted(() => {
  proxy.$mybus.off('mainScroll', setSelectDebounce)
})
function handleSelect(item: any) {
  location.hash = item.anchor
  $emit('select', item)
}
function setSelect(scrollDom: any) {
  if (!scrollDom) {
    return
  }
  activeAnchor.value = '' // 由于后续要重新设置，先清空之前的状态
  const range = 200
  for (const dom of doms.value) {
    // 看一下当前这个dom元素是不是应该被选中
    if (!dom) {
      continue
    }
    // 得到元素离视口顶部的距离
    const top = dom.getBoundingClientRect().top
    if (top >= 0 && top <= range) {
      // 在规定的范围内
      activeAnchor.value = dom.id
      return
    } else if (top > range) {
      // 在规定的范围下方
      return
    } else {
      // 在规定的范围上方
      activeAnchor.value = dom.id // 先假设自己是激活的，然后继续看后面
    }
  }
}
</script>

<style scoped lang="scss">
.blog-toc-container {
}
</style>
